/**
 * @description 深度从对象或数组中删除所有 false 值。
 * @param {*} val 
 * @returns 
 */
const compactObject = val => {
  // 判断该引用类型是数组还是对象
  const isArr = Object.prototype.toString.call(val) === '[object Array]'
  // 初始过滤当前层数组数据，避免稀疏矩阵，重复递归无用数据。
  // 在矩阵中，若数值为 0 的元素数目远远多于非 0 元素的数目，并且非 0 元素分布没有规律时，则称该矩阵为稀疏矩阵
  const data = isArr ? val.filter(Boolean) : val;
  // 遍历每个 key 值
  return Object.keys(data).reduce(
    (acc, key) => {
      const value = data[key];
      // 保存真实值
      if (Boolean(value))
        // 判断是否需递归
        acc[key] = typeof value === 'object' ? compactObject(value) : value;
      return acc;
    },
    // 初始化数组或对象
    isArr ? [] : {}
  );
};
// Examples
const obj = {
  a: null,
  b: false,
  c: true,
  d: 0,
  e: 1,
  f: '',
  g: 'a',
  h: [null, false, '', true, 1, 'a'],
  i: { j: 0, k: false, l: 'a' }
};
console.log(compactObject(obj));
// { c: true, e: 1, g: 'a', h: [ true, 1, 'a' ], i: { l: 'a' } }
